package com.hooya.fa.eu.biz.dao.manager;

import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.incrementer.IdentifierGenerator;
import com.hooya.fa.eu.api.bo.report.ProfitCheckBO;
import com.hooya.fa.eu.api.util.FileUtil;
import com.hooya.fa.eu.biz.dao.entity.ProfitCheck;
import com.hooya.fa.eu.biz.dao.entity.ProfitCheckDaily;
import com.hooya.fa.eu.biz.dao.entity.ProfitCheckRecord;
import com.hooya.fa.eu.biz.dao.entity.TempKcjlDaily;
import com.hooya.fa.eu.biz.dao.mapper.ProfitCheckDailyMapper;
import com.hooya.fa.eu.biz.dao.mapper.ProfitCheckMapper;
import com.hooya.fa.eu.biz.dao.mapper.ProfitCheckRecordMapper;
import com.hooya.fa.eu.biz.dao.mapper.TempKcjlDailyMapper;
import com.hooya.fa.eu.biz.dao.repository.ProfitCheckRecordRepository;
import com.hooya.fa.eu.biz.dao.repository.ProfitCheckRepository;
import com.hooya.fa.eu.biz.listener.ProfitCheckListener;
import com.hooya.integrated.common.core.util.DoubleUtil;
import com.hooya.integrated.common.other.data.DataMethod;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

import static com.hooya.fa.eu.api.constant.FileNameConstant.PROFIT_CHECK_FOLDER_NAME;

/**
 * @Description 1
 * @Author : Zongz
 * @Copyright Copyright (c) 豪雅集团
 * @Create 2025/3/22
 * @Version 1.1.0
 */
@Slf4j
@Component
@AllArgsConstructor
public class ProfitCheckManager {

    private final ProfitCheckRepository profitCheckRepository;

    private final ProfitCheckRecordRepository profitCheckRecordRepository;

    private final TempKcjlDailyMapper tempKcjlDailyMapper;

    private final ProfitCheckMapper profitCheckMapper;

    private final ProfitCheckDailyMapper profitCheckDailyMapper;

    private final ProfitCheckRecordMapper profitCheckRecordMapper;


    /**
     * 读取利润检查表数据并插入（古早处理方式）
     *
     * @param fileName            文件名称
     * @param date                日期
     * @param identifierGenerator id构造服务
     */
    public void readAndInsert(String fileName, String date, IdentifierGenerator identifierGenerator) {
        String path = FileUtil.getExcelPath() + PROFIT_CHECK_FOLDER_NAME + fileName;
        String belongs = fileName.split("_")[0];
        EasyExcel.read(path, ProfitCheckBO.class,
                new ProfitCheckListener(belongs, date, profitCheckRepository,
                        profitCheckRecordRepository, identifierGenerator)).sheet().doRead();
    }

    /**
     * 处理价格信息
     *
     * @param warehousing 进仓集合
     * @param inList      进仓数据
     */
    public void warehousingSku(List<ProfitCheckBO> warehousing, List<ProfitCheckBO> inList) {
        if (!CollectionUtils.isEmpty(inList)) {
            for (ProfitCheckBO bo : inList) {
                if (bo.getCurrency().equals("EUR")) {
                    bo.setCurrencyRate(bo.getEurPlnRate());
                    bo.setPln(DoubleUtil.mul(bo.getPrice(), bo.getEurPlnRate(), 2));
                    bo.setInPriceEur(bo.getPrice());
                    bo.setInPriceUsd(null);
                }
                if (bo.getCurrency().equals("USD")) {
                    bo.setCurrencyRate(bo.getUsdPlnRate());
                    bo.setPln(DoubleUtil.mul(bo.getPrice(), bo.getUsdPlnRate(), 2));
                    bo.setInPriceUsd(bo.getPrice());
                    bo.setInPriceEur(null);
                }
                if (bo.getCurrency().equals("PLN")) {
                    bo.setPln(bo.getPrice());
                    bo.setInPriceUsd(null);
                    bo.setInPriceEur(null);
                }
            }
            warehousing.addAll(inList);
        }
    }

    /**
     * 生成利润检查表相关信息
     *
     * @param id              主表id
     * @param day             日期
     * @param addProfit       主表集合
     * @param addProfitDaily  每日信息集合
     * @param addProfitRecord 价格等信息集合
     * @param profit          利润检查信息
     * @param createTime      创建时间
     * @param startNum        当日开始数量
     * @param endNum          当日结束数量
     * @param num             减扣数量
     * @param type            类型
     */
    public void genProfitInfo(Integer id, String day, List<ProfitCheck> addProfit, List<ProfitCheckDaily> addProfitDaily,
                              List<ProfitCheckRecord> addProfitRecord, ProfitCheckBO profit, LocalDateTime createTime,
                              Integer startNum, int endNum, int num, String type) {
        addProfit.add(ProfitCheck.builder().id(id).sku(profit.getSku()).invoiceNo(profit.getInvoiceNumber()).type("report")
                .belongs(profit.getBelongs()).remainingNum(endNum).date(day).createTime(createTime).build());
        addProfitDaily.add(ProfitCheckDaily.builder().profitCheckId(id).beginStockNum(startNum)
                .endStockNum(endNum).date(day).numFlag(startNum != endNum).build());
        ProfitCheckRecord record = ProfitCheckRecord.builder().profitCheckId(id).invoiceDate(profit.getInvoiceDate())
                .inboundDate(profit.getInboundDate()).beginStockNum(startNum).endStockNum(endNum)
                .inbound(profit.getInbound()).pln(profit.getPln()).inPriceEur(profit.getInPriceEur())
                .currencyRate(profit.getCurrencyRate()).type(profit.getType()).build();
        switch (type) {
            case "报损":
                record.setLost(num);
                break;
            case "退货":
                record.setRestock(num);
                break;
            case "b2b":
            case "b2c":
                record.setSales(num);
                break;
            case "转运":
                record.setTransfer(num);
                break;
            default:
                break;
        }
        addProfitRecord.add(record);
    }

    /**
     * 每日重复减扣数据（包含当日进出）
     *
     * @param trackId         跟踪号id
     * @param addProfit       主表
     * @param addProfitDaily  每日详情
     * @param addProfitRecord 价格等信息
     * @param endNum          最终数量
     * @param num             减扣数量
     * @param type            类型
     */
    public void deductedAgain(Integer trackId, List<ProfitCheck> addProfit, List<ProfitCheckDaily> addProfitDaily,
                              List<ProfitCheckRecord> addProfitRecord, int endNum, Integer num, String type) {
        addProfit.stream().filter(l -> l.getId().equals(trackId)).forEach(l -> l.setRemainingNum(endNum));
        addProfitDaily.stream().filter(l -> l.getProfitCheckId().equals(trackId)).forEach(l -> l.setEndStockNum(endNum));
        addProfitRecord.stream().filter(l -> l.getProfitCheckId().equals(trackId)).forEach(l -> {
            l.setEndStockNum(endNum);
            switch (type) {
                case "报损":
                    l.setLost(Objects.isNull(l.getLost()) ? num : (l.getLost() + num));
                    break;
                case "退货":
                    l.setRestock(Objects.isNull(l.getRestock()) ? num : (l.getRestock() + num));
                    break;
                case "b2b":
                case "b2c":
                    l.setSales(Objects.isNull(l.getSales()) ? num : (l.getSales() + num));
                    break;
                case "转运":
                    l.setTransfer(Objects.isNull(l.getTransfer()) ? num : (l.getTransfer() + num));
                    break;
                default:
                    break;
            }
        });
    }

    /**
     * 校验每日生成数据与库存相同
     *
     * @param day              日期
     * @param initialStageList 每日生成数据
     */
    public void checkDailySl(String day, List<ProfitCheckBO> initialStageList) {
        Map<String, Integer> skuMap = initialStageList.stream().filter(l -> l.getEndOfTheMonthStock() != 0)
                .collect(Collectors.toMap(ProfitCheckBO::getSku, ProfitCheckBO::getEndOfTheMonthStock, Integer::sum));
        List<TempKcjlDaily> kcList = tempKcjlDailyMapper.getDailyCostwayList(day);
        if (skuMap.keySet().size() != kcList.size()) {
            log.error(day + "的数量不一致，生成数量：" + skuMap.keySet().size() + "，库存数量：" + kcList.size());
        }
        Map<String, Integer> dailyMap = kcList.stream().collect(Collectors.toMap(TempKcjlDaily::getCpbh, TempKcjlDaily::getSl));
        dailyMap.forEach((k, v) -> {
            Integer sl = skuMap.get(k);
            if (Objects.isNull(sl)) {
                log.error("sku：" + k + " 不存在, 缺少数量为" + v);
                return;
            }
            if (!sl.equals(v)) {
                log.error("sku：" + k + " 数量不一致, 库存数量：" + v + "，生成数量：" + sl);
            }
        });
    }

    /**
     * 批量新增利润检查表相关信息
     *
     * @param addProfit       主表
     * @param addProfitDaily  每日详情
     * @param addProfitRecord 主表详情
     */
    public void insertProfit(List<ProfitCheck> addProfit, List<ProfitCheckDaily> addProfitDaily,
                             List<ProfitCheckRecord> addProfitRecord) {
        if (!CollectionUtils.isEmpty(addProfit)) {
            List<List<ProfitCheck>> profitSplit = DataMethod.splitData(addProfit, 2000);
            for (List<ProfitCheck> list : profitSplit) {
                profitCheckMapper.insertBatchSomeColumn(list);
            }
        }
        if (!CollectionUtils.isEmpty(addProfitDaily)) {
            List<List<ProfitCheckDaily>> dailySplit = DataMethod.splitData(addProfitDaily, 2000);

            for (List<ProfitCheckDaily> list : dailySplit) {
                profitCheckDailyMapper.insertBatchSomeColumn(list);
            }
        }
        if (!CollectionUtils.isEmpty(addProfitRecord)) {
            List<List<ProfitCheckRecord>> recordSplit = DataMethod.splitData(addProfitRecord, 2000);
            for (List<ProfitCheckRecord> list : recordSplit) {
                profitCheckRecordMapper.insertBatchSomeColumn(list);
            }
        }
    }

}
